package com.yunbiao.ybbusstopplate.refactoring.ui.fengxian;

import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;

import com.blankj.utilcode.util.ConvertUtils;
import com.blankj.utilcode.util.FileIOUtils;
import com.blankj.utilcode.util.GsonUtils;
import com.blankj.utilcode.util.UiMessageUtils;
import com.example.library_hy_advert.system.Cache;
import com.google.gson.reflect.TypeToken;
import com.yunbiao.ybbusstopplate.bean.SiteInfoBean;
import com.yunbiao.ybbusstopplate.refactoring.agreement.base.ProtocolParser;
import com.yunbiao.ybbusstopplate.refactoring.ui.dalian.ZHIDAParser;
import com.yunbiao.ybbusstopplate.refactoring.utils.Utils;
import com.yunbiao.ybbusstopplate.utils.BytesUtils;
import com.yunbiao.ybbusstopplate.utils.StringUtils;

import java.io.File;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import tp.xmaihh.serialport.SerialHelper;
import tp.xmaihh.serialport.bean.ComBean;

public class TONGDA2020Parser extends ProtocolParser {
    private static final String TAG = "TONGDA2020Parser";

    private static final DateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");

    private StringBuilder hexString = null;
    private String device = "";


    private static final String KEY_SITE_LIST = "key_tongda2020_site_list";
    private static final String KEY_LINE_NAME = "key_tongda2020_line_name";
    private static final String KEY_START_SITE = "key_tongda2020_start_site";
    private static final String KEY_END_SITE = "key_tongda2020_end_site";
    private static final String KEY_START_TIME = "key_tongda2020_start_time";
    private static final String KEY_END_TIME = "key_tongda2020_end_time";
    private static final String KEY_LAST_DIRECTION = "key_tongda2020_last_direction";
    private static final String KEY_LAST_INDEX = "key_tongda2020_last_index";
    private static final String KEY_LAST_INOUT = "key_tongda2020_last_inout";


    private final LinkedHashMap<Integer, ZHIDAParser.Site> siteMap = new LinkedHashMap<>();

    @Override
    public void loadCache() {
        String string = Cache.getString(KEY_SITE_LIST);
        if(!TextUtils.isEmpty(string)){
            List<ZHIDAParser.Site> list = GsonUtils.fromJson(string,new TypeToken<List<ZHIDAParser.Site>>(){}.getType());
            siteMap.clear();
            for (ZHIDAParser.Site site : list) {
                siteMap.put(site.getIndex(),site);
            }
        }

        sendList();
        sendLineName();
        sendStartEndSiteAndTime();

        String upDown = Cache.getString(KEY_LAST_DIRECTION);
        String inOut = Cache.getString(KEY_LAST_INOUT);
        int index = Cache.getInt(KEY_LAST_INDEX);
        sendBroadSite(upDown,inOut,index);
    }

    private void sendList(){
        ZHIDAParser.Site[] array = siteMap.values().toArray(new ZHIDAParser.Site[0]);
        UiMessageUtils.getInstance().send(ZHIDAParser.Event.UPDATE_SITE_LIST.getType(),array);
    }

    private void sendLineName(){
        String name = Cache.getString(KEY_LINE_NAME);
        UiMessageUtils.getInstance().send(ZHIDAParser.Event.UPDATE_LINE_NAME.getType(),name);
    }

    private void sendStartEndSiteAndTime(){
        String startSite = Cache.getString(KEY_START_SITE);
        String endSite = Cache.getString(KEY_END_SITE);
        String upStartEndSite = startSite + " - " + endSite;
        String upStartTime = Cache.getString(KEY_START_TIME);
        String upEndTime = Cache.getString(KEY_END_TIME);

        String downStartEndSite = "";
        String downStartTime = "";
        String downEndTime = "";
        UiMessageUtils.getInstance().send(ZHIDAParser.Event.UPDATE_START_END.getType(),new String[]{
                upStartEndSite,downStartEndSite,
                upStartTime,upEndTime,
                downStartTime,downEndTime
        });
    }

    private void sendBroadSite(String upDown,String inOut,int siteIndex){
        Log.e(TAG, "111 sendBroadSite: " + upDown + " --- " + inOut + " --- " + siteIndex);

        if(!siteMap.isEmpty()){
            Log.e(TAG, "222 sendBroadSite: " + upDown + " --- " + inOut + " --- " + siteIndex);

            ZHIDAParser.Site currSite = siteMap.get(siteIndex);

            if(currSite != null){
                UiMessageUtils.getInstance().send(ZHIDAParser.Event.BROAD_SITE.getType(),new Object[]{currSite,siteIndex,"0".equals(inOut) ? "01" : "00",upDown});
            }
        }
    }

    @Override
    public void analyzing(SerialHelper serialHelper, ComBean comBean) throws Throwable {
        byte[] bytes = comBean.bRec;
        if (bytes == null) {
            Log.d(TAG,"bytes is null");
            return;
        }
        if (hexString == null) {
            hexString = new StringBuilder();
        }
        //起始字节
        byte[] start = BytesUtils.SubByte(bytes, 0, 2);
        String startHex = BytesUtils.bytesToHex(start);

        //485转TTL有时候会出现结尾5500的情况，需要把结尾的00去掉之后再校验
        byte[] end1 = BytesUtils.SubByte(bytes,bytes.length - 2,2);
        String endHex2 = BytesUtils.bytesToHex(end1);
//        Log.d(TAG, "analysisData: 结尾：" + endHex2);
        if(TextUtils.equals("5500",endHex2)){
//            Log.d(TAG, "analysisData: 结尾是5500，截取后解析");
            bytes = BytesUtils.SubByte(bytes,0,bytes.length - 1);
        }

        //末尾字节
        byte end = bytes[bytes.length - 1];
        String endHex = BytesUtils.byteToHex(end);

        //开始
        if ("bb10".equals(startHex)) {
//            Log.d(TAG, "-----------start---------");
            hexString.delete(0, hexString.length());
            device = BytesUtils.byteToHex(bytes[1]);
        }
        //存储数据
        hexString.append(BytesUtils.bytesToHex(bytes));
        //结束
        if ("55".equals(endHex)) {
//            Log.d(TAG, "-----------end---------");
//            Log.d(TAG, "--->" + hexString.toString());
            String splitStr = "bb" + device;
            String[] hexArray = hexString.toString().split(splitStr);
            hexString.setLength(0);

            for (String ss : hexArray) {
                if (ss != null && !"".equals(ss)) {
                    byte[] byteArray = BytesUtils.hexToByteArray(splitStr + ss);
                    chioseAgr(byteArray);
                }
            }
        }
    }

    private void chioseAgr(byte[] bytes) {
        try {
//            String s = BytesUtils.bytesToHex(bytes);
//            Log.d(TAG, "chioseAgr: " + s);

            byte ADDR = bytes[1];
            byte CMD = bytes[3];
            byte[] data = BytesUtils.SubByte(bytes, 4, bytes.length - 7);

            if(ADDR != (byte)0X10){
                return;
            }

            //判断是否是时间
            if(CMD == (byte)0x11 && data.length == 7){
                try {
                    String string = BytesUtils.bytesToHex(data);
                    Date parse = sdf.parse(string);
                    d("是时间：" + string);
                    return;
                } catch (ParseException e) {
                    Log.e(TAG, "chioseAgr: ", e);
                }
            }

            Queue<Byte> byteQueue = new LinkedList<>();
            for (byte datum : data) {
                byteQueue.add(datum);
            }

            switch (CMD) {
                case (byte)0x02://路牌字符（线路信息）
                    resolveGuideBoardWord(byteQueue);
                    break;
                case (byte)0x08://报站
                    broadSite(byteQueue);
                    break;
                case (byte)0x11://侧牌站点（站点列表）
                    siteList(byteQueue);
                    break;
                case (byte)0x12://首末班时间
                    firstLastTime(byteQueue);
                    break;
            }
        }  catch (Exception e) {
            e("解析异常：" + e);
//            if (agreementListener != null) {
//                agreementListener.agreementFailed();
//            }
        }
    }

    private String startSite,endSite;
    //路牌字符
    private void resolveGuideBoardWord(Queue<Byte> byteQueue){
        // BB 10 1F 02 0B B2 DC D6 BE BA C0 37 30 37 CF DF 04 BB AA CF C4 08 BB A8 C7 C5 C9 E7 C7 F8 86 10 55
        // BB 起始
        // 10 硬件地址
        // 1F 长度
        // 02 命令字
        // 0B 线路号长度
        // B2 DC D6 BE BA C0 37 30 37 CF DF 线路号字符
        // 04 起点长度
        // BB AA CF C4 起点字符
        // 08 终点长度
        // BB A8 C7 C5 C9 E7 C7 F8 终点字符
        // 86 SUML
        // 10 SUMH
        // 55 结尾
        int length = BytesUtils.hex16to10(BytesUtils.byteToHex(byteQueue.poll()));
        String lineNumber = StringUtils.hexStringToString(BytesUtils.bytesToHex(getBytes(byteQueue,length)));

        length = BytesUtils.hex16to10(BytesUtils.byteToHex(byteQueue.poll()));
        startSite = StringUtils.hexStringToString(BytesUtils.bytesToHex(getBytes(byteQueue,length)));

        length = BytesUtils.hex16to10(BytesUtils.byteToHex(byteQueue.poll()));
        endSite = StringUtils.hexStringToString(BytesUtils.bytesToHex(getBytes(byteQueue,length)));

        d("线路号：" + lineNumber + " , " + "起点字符：" + startSite + " , " + "终点字符：" + endSite);

        Cache.setString(KEY_LINE_NAME,lineNumber);
        Cache.setString(KEY_START_SITE,startSite);
        Cache.setString(KEY_END_SITE,endSite);

        sendLineName();
        sendStartEndSiteAndTime();

//        if(agreementListener != null){
//            agreementListener.onLineInfoResult(new String[]{lineNumber,startSite,endSite});
//        }
    }

    //报站
    private void broadSite(Queue<Byte> byteQueue){
        // bb 10 12
        // 08
        // 81 09
        // 20 d1 f3 cd b7 20 b5 bd c1 cb 20
        // 5a 07 55

        String s1 = ConvertUtils.bytes2Bits(new byte[]{byteQueue.poll()});
        char[] chars = s1.toCharArray();
        String inOut = String.valueOf(chars[0]);
        chars = Arrays.copyOfRange(chars, 1, chars.length);
        byte[] bytes = ConvertUtils.bits2Bytes(String.valueOf(chars));
        int index = Integer.parseInt(BytesUtils.bytesToHex(bytes));
        Log.d(TAG, "broadSite: " + inOut + " --- " + index);

        String s2 = ConvertUtils.bytes2Bits(new byte[]{byteQueue.poll()});
        char[] chars1 = s2.toCharArray();
        String upDown = String.valueOf(chars1[0]);
        chars1 = Arrays.copyOfRange(chars1, 1, chars1.length);
        byte[] bytes1 = ConvertUtils.bits2Bytes(String.valueOf(chars1));
        int count = Integer.parseInt(BytesUtils.bytesToHex(bytes1));
        Log.d(TAG, "broadSite: " + upDown + " --- " + count);

        byte[] contentBytes = new byte[byteQueue.size()];
        for (int i = 0; i < contentBytes.length; i++) {
            contentBytes[i] = byteQueue.poll();
        }
        String content = Utils.hexStringToString(Utils.bytesToHex(contentBytes));
        Log.d(TAG, "broadSite: " + content);

        Cache.setString(KEY_LAST_DIRECTION, upDown);
        Cache.setInt(KEY_LAST_INDEX, index);
        Cache.setString(KEY_LAST_INOUT, inOut);

        sendBroadSite(upDown,inOut,index);
    }

    private boolean isRefreshList = false;

    //线路站点
    private void siteList(Queue<Byte> byteQueue) {
        // BB 10 50 11 08 00 04 BB AA CF C4 01 08 BF AA B8 A3 CB C2 B6 AB 02 06 D6 F1 C9 BD D4 B0 03 0A CF E6 D1 C5 C2 B7 CE F7 BF DA 04 06 B3 B1 D7 DA BD D6 05 08 BB F0 D1 E6 C2 B7 BF DA 06 08 D7 D8 CA F7 C2 B7 BF DA 07 08 BB A8 C7 C5 C9 E7 C7 F8 68 2E 55
        // BB 起始
        // 10 硬件地址
        // 50 长度
        // 11 命令字
        // 08 站点总数
        // 00 站点序号
        // 04 站点名长度
        // BB AA CF C4 站点名
        // 01
        // 08
        // BF AA B8 A3 CB C2 B6 AB
        // 02
        // 06
        // D6 F1 C9 BD D4 B0
        // 03
        // 0A
        // CF E6 D1 C5 C2 B7 CE F7 BF DA
        // 04
        // 06
        // B3 B1 D7 DA BD D6
        // 05
        // 08
        // BB F0 D1 E6 C2 B7 BF DA
        // 06
        // 08
        // D7 D8 CA F7 C2 B7 BF DA
        // 07
        // 08
        // BB A8 C7 C5 C9 E7 C7 F8
        // 68
        // 2E
        // 55
        int siteCount = BytesUtils.hex16to10(BytesUtils.byteToHex(byteQueue.poll()));
//        d("站点总数：" + siteCount);

        int tag = 0;
        int length = 0;
        int siteIndex = 0;
        readList:while (!byteQueue.isEmpty()) {
            switch (tag) {
                case 0:
                    siteIndex = BytesUtils.hex16to10(BytesUtils.byteToHex(byteQueue.poll()));
//                    d("站点序号：" + siteIndex);
                    if(siteIndex == 0){
                        d("发现起始站，清除旧数据");
                        siteMap.clear();
                        isRefreshList = true;
                    }
                    tag = 1;
                    break;
                case 1:
                    length = BytesUtils.hex16to10(BytesUtils.byteToHex(byteQueue.poll()));
//                    d("站点名长度：" + length);
                    tag = 2;
                    break;
                case 2:
                    String siteName = StringUtils.hexStringToString(BytesUtils.bytesToHex(getBytes(byteQueue,length)));
                    d("站点名：" + siteIndex + "_" + siteName + "，站点总数：" + siteCount + " --- " + (isRefreshList && siteMap.size() < siteCount));
                    //增加站名收集控制，如果不在刷新状态则不添加
                    if(isRefreshList && siteMap.size() < siteCount){
                        siteMap.put(siteIndex,new ZHIDAParser.Site(siteIndex,siteName,""));
                        if(siteMap.size() >= siteCount){
                            Log.d(TAG, "handleSiteList: ------------------------------ ");
                            break readList;
                        }
                    }
                    tag = 0;
                    break;
            }
        }

        if(isRefreshList && siteMap.size() >= siteCount){
            isRefreshList = false;
            if(siteCount != siteMap.size()){
                e("获取站点列表完成，通知界面刷新：" + siteCount + " , " + siteMap.size() + " , " + siteMap);
                e("站点列表数量错误");
            } else {
                d("获取站点列表完成，通知界面刷新：" + siteCount + " , " + siteMap.size() + " , " + siteMap);
                d("站点列表数量正确");
            }

            Cache.setString(KEY_SITE_LIST, GsonUtils.toJson(siteMap.values()));
//            Integer min = Collections.min(siteMap.keySet());
//            Integer max = Collections.max(siteMap.keySet());
//            ZHIDAParser.Site firstSite = siteMap.get(min);
//            ZHIDAParser.Site lastSite = siteMap.get(max);
            sendList();
        }
    }

    //首末班时间
    private void firstLastTime(Queue<Byte> byteQueue){
        // bb 10 09 12 06 00 16 1e 00 65 55
        // bb 起始
        // 10 硬件地址
        // 09 长度
        // 12 命令字
        // 06 00 首班
        // 16 1e 末班
        // 00 SUML
        // 65 SUMH
        // 55 结尾
        int startHourInt = BytesUtils.hex16to10(BytesUtils.byteToHex(byteQueue.poll()));
        String startHour = startHourInt < 10 ? ("0" + startHourInt) : ( "" + startHourInt);
        int startMinutesInt = BytesUtils.hex16to10(BytesUtils.byteToHex(byteQueue.poll()));
        String startMinutes = startMinutesInt < 10 ? ("0" + startMinutesInt) : ( "" + startMinutesInt);
        String startTime = startHour + ":" + startMinutes;
        d("开始时间：" + startTime);
        int endHourInt = BytesUtils.hex16to10(BytesUtils.byteToHex(byteQueue.poll()));
        String endHour = endHourInt < 10 ? ("0" + endHourInt) : ( "" + endHourInt);
        int endMinutesInt = BytesUtils.hex16to10(BytesUtils.byteToHex(byteQueue.poll()));
        String endMinutes = endMinutesInt < 10 ? ("0" + endMinutesInt) : ( "" + endMinutesInt);
        String endTime = endHour + ":" + endMinutes;
        d("结束时间：" + endTime);

        Cache.setString(KEY_START_TIME,startTime);
        Cache.setString(KEY_END_TIME,endTime);
        sendStartEndSiteAndTime();

//        if (agreementListener!=null){
//            agreementListener.onSiteTimeResult(startTime,endTime,"","");
//        }
    }

    private byte[] getBytes(Queue<Byte> byteQueue,int length){
        byte[] bytes = new byte[length];
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = byteQueue.poll();
        }
        return bytes;
    }
    /**
     * Bit转Byte
     */
    public static byte BitToByte(String byteStr) {
        int re, len;
        if (null == byteStr) {
            return 0;
        }
        len = byteStr.length();
        if (len != 4 && len != 8) {
            return 0;
        }
        if (len == 8) {// 8 bit处理
            if (byteStr.charAt(0) == '0') {// 正数
                re = Integer.parseInt(byteStr, 2);
            } else {// 负数
                re = Integer.parseInt(byteStr, 2) - 256;
            }
        } else {//4 bit处理
            re = Integer.parseInt(byteStr, 2);
        }
        return (byte) re;
    }

    private void d(String log){
        Log.d(TAG, log);
//        LogUtils.dTag(TAG,log);
    }

    private void e(String error){
        Log.e(TAG, error);
//        LogUtils.eTag(TAG,error);
    }

    public void test(){
        File file = new File(Environment.getExternalStorageDirectory(),"test3.txt");
        List<String> strings1 = FileIOUtils.readFile2List(file);
        for (String s : strings1) {
            if (s.contains("<---")) {
                String[] split = s.split("<---");
                String s1 = split[1];
                byte[] bytes = Utils.hexToByteArray(s1);
                ComBean comBean = new ComBean("",bytes,bytes.length);
                try {
                    analyzing(null,comBean);
                } catch (Throwable e) {
                    Log.e(TAG, "test: ", e);
                }
            }
        }


//        String[] strings = {
//            "BB 10 1F 02 0B B2 DC D6 BE BA C0 37 30 37 CF DF 04 BB AA CF C4 08 BB A8 C7 C5 C9 E7 C7 F8 86 10 55",
//            "bb 10 09 12 06 00 16 1e 00 65 55",
//            "bb 10 d2 11 31 00 0c b0 c4 cd b7 b3 b5 b3 a1 d7 dc d5 be 01 08 b0 c4 cd b7 d7 dc d5 be 02 0c b2 bc bc aa bd bb be af d6 d0 b6 d3 03 06 b1 a6 b6 a6 cd fe 04 08 b1 a6 b9 da c2 b7 bf da 05 08 b2 bc c0 bd c2 b7 bf da 06 06 b9 f0 b7 bc d4 b0 07 0c b4 f3 b7 d2 b5 d8 cc fa d5 be a2 d9 08 0c c4 be c3 de cd e5 b5 d8 cc fa d5 be 09 08 c1 fa d6 e9 bb a8 d4 b0 0a 08 c8 d9 b3 ac bb a8 d4 b0 0b 0a b2 bc bc aa c1 aa bc ec d5 be 0c 06 c4 e0 b8 da c7 c5 0d 08 ba ec b8 da bb a8 d4 b0 0e 0a b1 a6 b0 b2 b1 b1 c2 b7 bf da 0f 06 c4 e0 b8 da b4 e5 10 06 c4 e0 b8 da ce f7 11 08 ca d0 bb b0 b4 f3 cf c3 12 0c ba a3 cd e2 d7 b0 ca ce b4 f3 cf c3 34 82 55",
//            "bb 10 dc 11 31 13 08 d5 f1 bb aa ce f7 c2 b7 14 08 d6 d0 d0 c4 b9 ab d4 b0 15 08 c8 cb b2 c5 b4 f3 cf c3 16 0a ca d0 c3 f1 d6 d0 d0 c4 b6 ab 17 0e b4 f3 d6 d0 bb aa b9 fa bc ca b9 e3 b3 a1 18 0c d7 bf d4 bd ca b1 b4 fa b9 e3 b3 a1 19 08 b9 ba ce ef b9 ab d4 b0 1a 08 cd b6 d7 ca b4 f3 cf c3 1B 08 cc d8 c7 f8 b1 a8 c9 e7 1c 06 cf e3 c3 db ba fe 1d 0c c9 ee c4 cf cf e3 c3 db c1 a2 bd bb 1e 06 d6 f1 d7 d3 c1 d6 1f 08 bf b5 bc d1 bc af cd c5 20 08 bd f5 d0 e5 d6 d0 bb aa 21 0c ba ce cf e3 c4 fd c3 c0 ca f5 b9 dd 22 08 ca c0 bd e7 d6 ae b4 b0 23 04 b4 f3 b3 e5 24 06 bf c6 bc bc d4 b0 25 08 c0 f3 cf e3 b9 ab d4 b0 26 0c c4 cf d0 c2 c9 ee c4 cf cc ec c7 c5 67 8d 55",
//            "bb 10 6c 11 31 27 0a c4 cf c9 bd bb b6 c0 d6 cb cc 28 08 c4 cf c3 b3 ca d0 b3 a1 29 06 cc ef cf c3 b4 e5 2a 08 b4 f3 c2 bd d7 af d4 b0 2b 08 c4 cf c9 bd ca d0 b3 a1 2c 08 bb aa c1 aa bb a8 d4 b0 2d 06 c4 cf d4 b0 b4 e5 2e 08 c4 cf c9 bd b4 e5 b1 b1 2f 06 c4 cf c9 bd b4 e5 30 0e b3 c7 ca d0 c9 bd c1 d6 b6 ab d7 dc d5 be 93 41 55",
//            "BB 10 1C 08 02 09 20 4E 65 78 74 20 53 74 61 74 69 6F 6E 3A 20 57 65 73 65 6E 20 7C 07 55",
//            "bb 10 12 08 81 09 20 d1 f3 cd b7 20 b5 bd c1 cb 20 5a 07 55",
//            "bb 10 12 08 82 09 20 b8 a3 c9 bd 20 b5 bd c1 cb 20 f4 06 55",
//        };
//
//        for (String string : strings) {
//            String hex = string.replaceAll(" ", "");
//            byte[] bytes = Utils.hexToByteArray(hex);
//
//            ComBean comBean = new ComBean("",bytes,bytes.length);
//            try {
//                analyzing(null,comBean);
//            } catch (Throwable e) {
//                Log.e(TAG, "test: ", e);
//            }
//        }
    }
}
